<?php
// 应用公共文件  11111

//循环创建目录
function mkdirs($dir, $mode = 0777)
{
    if (!is_dir($dir)) {
        mkdirs(dirname($dir), $mode);
        return mkdir($dir, $mode);
    }
    return true;
}

//循环删除某个目录及目录下的文件
function deldir($path){
    //如果是目录则继续
    if(is_dir($path)){
        //扫描一个文件夹内的所有文件夹和文件并返回数组
        $p = scandir($path);
        foreach($p as $val){
            //排除目录中的.和..
            if($val !="." && $val !=".."){
                //如果是目录则递归子目录，继续操作
                if(is_dir($path.$val)){
                    //子目录中操作删除文件夹和文件
                    deldir($path.$val.'/');
                    //目录清空后删除空文件夹
                    @rmdir($path.$val.'/');
                    echo "删除成功";
                }else{
                    //如果是文件直接删除
                    unlink($path.$val);
                }
            }
        }
    }
    //最后删除目录自身
    @rmdir($path);
}

/**
 * 字节数Byte转换为KB、MB、GB、TB
 * @param int $size
 * @return string
 */
function xn_file_size($size){
    $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
    for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
    return round($size, 2) . $units[$i];
}

/**
 * 驼峰命名转下划线命名
 * @param $camelCaps
 * @param string $separator
 * @return string
 */
function xn_uncamelize($camelCaps,$separator='_')
{
    return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
}

/**
 * 密码加密函数
 * @param $password
 * @return string
 */
function xn_encrypt($password)
{
    $salt = 'xiaoniu_admin';
    return md5(md5($password.$salt));
}

/**
 * 管理员操作日志
 * @param $remark
 */
function xn_add_admin_log($remark,$notparam=false)
{
    return false;
    $data = [
        'admin_id' => session('admin_auth.id'),
        'url' => request()->url(true),
        'ip' => request()->ip(),
        'remark' => $remark,
        'method' =>request()->method(),
        'param' => !$notparam ? json_encode(request()->param()):'',
        'create_time' => time()
    ];
    \app\common\model\AdminLog::insert($data);
}

/**
 * 获取自定义config系统配置
 * 用法： xn_cfg('base') 或 xn_cfg('base.website') 不支持无限极
 * @param string|null $name
 * @param string|null $default
 * @param string|null $path
 * @return array|string
 */
function xn_cfg($name, $default='', $path='cfg')
{
    return \think\facade\Config::get('tutu_system.'.$name,$default);
}

/**
 * 设置动态配置项
 * @param $name  配置名
 * @param $value 配置值
 */
function setENV($name,$value){
    $env = file_get_contents(ROOT_PATH.'.env');
    $pattern = "#{$name}\s*\=\s*.*?(\s+)#";
    $env = preg_replace($pattern,"{$name} = ".$value.'${1}',$env);
    @file_put_contents(ROOT_PATH.'.env',$env);
}

/**
 * 根目录物理路径
 * @return string
 */
function xn_root()
{
    return app()->getRootPath() . 'public';
}

/**
 * 构建图片上传HTML 单图
 * @param string $value
 * @param string $file_name
 * @param null $water 是否添加水印 null-系统配置设定 1-添加水印 0-不添加水印
 * @param null $thumb 生成缩略图，传入宽高，用英文逗号隔开，如：200,200（仅对本地存储方式生效，七牛、oss存储方式建议使用服务商提供的图片接口）
 * @return string
 */
function xn_upload_one($value,$file_name,$water=null,$thumb=null)
{
$html=<<<php
    <div class="xn-upload-box">
        <div class="t layui-col-md12 layui-col-space10">
            <input type="hidden" name="{$file_name}" class="layui-input xn-images" value="{$value}">
            <div class="layui-col-md4">
                <div type="button" class="layui-btn webuploader-container" id="{$file_name}" data-water="{$water}" data-thumb="{$thumb}" style="width: 113px;"><i class="layui-icon layui-icon-picture"></i>上传图片</div>
                <div type="button" class="layui-btn chooseImage" data-num="1"><i class="layui-icon layui-icon-table"></i>选择图片</div>
            </div>
        </div>
        <ul class="upload-ul clearfix">
            <span class="imagelist"></span>
        </ul>
        <script>$('#{$file_name}').uploadOne();</script>
    </div>
php;
    return $html;
}

/**
 * 构建图片上传HTML 多图
 * @param string $value
 * @param string $file_name
 * @param null $water 是否添加水印 null-系统配置设定 1-添加水印 0-不添加水印
 * @param null $thumb 生成缩略图，传入宽高，用英文逗号隔开，如：200,200（仅对本地存储方式生效，七牛、oss存储方式建议使用服务商提供的图片接口）
 * @return string
 */
function xn_upload_multi($value,$file_name,$water=null,$thumb=null)
{
    $html=<<<php
    <div class="xn-upload-box">
        <div class="t layui-col-md12 layui-col-space10">
            <div class="layui-col-md8">
                <input type="text" name="{$file_name}" class="layui-input xn-images" value="{$value}">
            </div>
            <div class="layui-col-md4">
                <div type="button" class="layui-btn webuploader-container" id="{$file_name}" data-water="{$water}" data-thumb="{$thumb}" style="width: 113px;"><i class="layui-icon layui-icon-picture"></i>上传图片</div>
                <div type="button" class="layui-btn chooseImage"><i class="layui-icon layui-icon-table"></i>选择图片</div>
            </div>
        </div>
        <ul class="upload-ul clearfix">
            <span class="imagelist"></span>
        </ul>
        <script>$('#{$file_name}').upload();</script>
    </div>
php;
    return $html;
}


/**
 * 构建富文本框
 */
if(!function_exists('xn_ueditor')){
    function xn_ueditor($id, $value = '', $options = array()) {
        $s = '';
        if (!defined('TPL_INIT_UEDITOR')) {
            $s .= '<script type="text/javascript" src="/static/admin/ueditor/ueditor.config.js"></script>
			<script type="text/javascript" src="/static/admin/ueditor/ueditor.all.min.js"></script>
			<script type="text/javascript" src="/static/admin/ueditor/lang/zh-cn/zh-cn.js"></script>';
        }
        $options['height'] = empty($options['height']) ? 200 : $options['height'];
        $options['width'] = empty($options['width']) ? 800 : $options['width'];
        $options['allow_upload_video'] = isset($options['allow_upload_video']) ? $options['allow_upload_video'] : true;
        $options['dest_dir'] = isset($options['dest_dir']) ? $options['dest_dir'] : '';

        $s .= !empty($id) ? "<textarea id=\"{$id}\" name=\"{$id}\" type=\"text/plain\" style=\"height:{$options['height']}px;\">{$value}</textarea>" : '';
        $s .= "
		<script type=\"text/javascript\">
		var ueditoroption = {
		'autoClearinitialContent' : false,
		'toolbars' : [['fullscreen', 'source', 'preview', '|', 'bold', 'italic', 'underline', 'strikethrough', 'forecolor', 'backcolor', '|',
		'justifyleft', 'justifycenter', 'justifyright', '|', 'insertorderedlist', 'insertunorderedlist', 'blockquote', 'emotion','insertimage',
		'link', 'removeformat', '|', 'rowspacingtop', 'rowspacingbottom', 'lineheight','indent', 'paragraph', 'fontsize', '|',
		'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol',
		'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', '|', 'anchor', 'map', 'print', 'drafts']],
		'elementPathEnabled' : false,
		'initialFrameHeight': {$options['height']},
		'focus' : false,
		'initialFrameWidth':{$options['width']},
		'maximumWords' : 9999999999999
		};
	\".(!empty($id) ? \"
	$(function(){
	var ue = UE.getEditor('{$id}', ueditoroption);
	$('#{$id}').data('editor', ue);
	$('#{$id}').parents('form').submit(function() {
	if (ue.queryCommandState('source')) {
	ue.execCommand('source');
	}
	});
	});\" : '').\"
	</script>";
        return $s;
    }

}

/**
 *  快捷构建配置视图
 *  支持的标签有  text  checkbox  textarea img
 * @param $data  页面数据
 * @param $option  标签配置
 * @param string $name 二维数组时 可传参数
 * @return string
 */
function xn_ConfigView($data,$option,$parent=''){
    $html_top = <<<text
<div class="layui-form-item">
    <label class="layui-form-label">[title]</label>
    <div class="layui-input-block">
text;
    //文本
    $text = <<<text
     <input type="text" name="[name]" value="[value]" placeholder="[placeholder]" class="layui-input"></div></div>
text;
    // 开关标签
    $checkbox = <<<text
        <input type="checkbox" name="[name]" value="1" [value] lay-skin="switch" lay-text="开启|关闭"></div></div>
text;
    //多行文本
    $textarea = <<<text
<textarea name="[name]" class="layui-textarea" placeholder="[placeholder]">[value]</textarea></div></div>
text;
    $html = '<div class="layui-form" wid100="" lay-filter="">';
    foreach ($option as $k=>$item){
        $html_item = str_replace("[title]",$item['title'],$html_top);
        if($parent){
            $value = $data[$parent][$item['name']]?:$item['default'];
            $name = $parent."[{$item['name']}]";
        }else{
            $value = $data[$item['name']]?:$item['default'];
            $name = $item['name'];
        }
        $placeholder = $item['placeholder']?:'';

        switch ($item['type']){
            //文本框
            case 'text':
                $html_item.=str_replace(['[name]','[value]','[placeholder]'],[$name,$value,$placeholder],$text);
                break;
            //开关
            case 'checkbox':
                $html_item.=str_replace(['[name]','[value]','[placeholder]'],[$name,$value==1?'checked':'',$placeholder],$checkbox);
                break;
            case 'textarea':
                $html_item.=str_replace(['[name]','[value]','[placeholder]'],[$name,$value,$placeholder],$textarea);
                break;
            case 'img':
                $html_item.= xn_upload_one($value,$name,0)."</div></div>";
                break;
        }
        $html .=$html_item."\r\n";
    }
    $html.="</div>";
    return $html;
}



/**
 * 格式化标签，将空格、中文逗号替换成英文半角分号
 * @param $tags
 * @return string
 */
function xn_format_tags($tags)
{
    $tags = trim($tags);
    $tags = str_replace(' ',',',str_replace('，',',',$tags));
    $arr = explode(',',$tags);
    $data = [];
    foreach ($arr as $v) {
        if( $v!='' ) {
            $data[] = $v;
        }
    }
    return implode(',',$data);
}

/**
 * 生成全局唯一标识符
 * @param bool $trim
 * @return string
 */
function xn_create_guid()
{
    $charid = strtoupper(md5(uniqid(mt_rand(), true)));
    $hyphen = chr(45);// "-"
    $uuid = chr(123)// "{"
        .substr($charid, 0, 8).$hyphen
        .substr($charid, 8, 4).$hyphen
        .substr($charid,12, 4).$hyphen
        .substr($charid,16, 4).$hyphen
        .substr($charid,20,12)
        .chr(125);// "}"
    return $uuid;
}

//生成订单号
function xn_create_order_no() {
    $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
    $orderSn = $yCode[intval(date('Y')) - 2020] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
    return $orderSn;
}

/**
 * Notes:生成唯一订单ID  传入用户id 如若用户id大于
 * User: 戴杰
 * Date: 2018/9/25 0025
 * @param $userid 用户id
 */
function getOrdersn($userid, $prefix = "S",$length=16)
{
    //S 180925095543 12345 28
//    $length = 16;//订单号总长度
    $tmpstr1 = rand(0, 9);
    $tmpstr2 = rand(0, 9);
    $ordersn = $prefix . $tmpstr1 . $tmpstr2 . date('YmdHis') . $userid;//10~15位
    $leng = strlen($ordersn);
    $len = $length - $leng - 1;//需要补齐的长度
    while ($len > 7) {
        $pow = pow(10, 7);
        $rand = mt_rand($pow, $pow * 9);
        $len -= 8;
        $ordersn = $ordersn . $rand;
    }
    $pow = pow(10, $len);
    $rand = mt_rand($pow, $pow * 9);
    if ($rand > 0)
        $ordersn = $ordersn . $rand;
    return $ordersn;
}

/**
 * 列出本地目录的文件
 * @author rainfer <81818832@qq.com>
 * @param string $path
 * @param string $pattern
 * @return array
 */
function list_file($path, $pattern = '*')
{
    if (strpos($pattern, '|') !== false) {
        $patterns = explode('|', $pattern);
    } else {
        $patterns [0] = $pattern;
    }
    $i = 0;
    $dir = array();
    if (is_dir($path)) {
        $path = rtrim($path, '/') . '/';
    }
    foreach ($patterns as $pattern) {
        $list = glob($path . $pattern);
        if ($list !== false) {
            foreach ($list as $file) {
                $dir [$i] ['filename'] = basename($file);
                $dir [$i] ['path'] = dirname($file);
                $dir [$i] ['pathname'] = realpath($file);
                $dir [$i] ['owner'] = fileowner($file);
                $dir [$i] ['perms'] = substr(base_convert(fileperms($file), 10, 8), -4);
                $dir [$i] ['atime'] = fileatime($file);
                $dir [$i] ['ctime'] = filectime($file);
                $dir [$i] ['mtime'] = filemtime($file);
                $dir [$i] ['size'] = filesize($file);
                $dir [$i] ['type'] = filetype($file);
                $dir [$i] ['ext'] = is_file($file) ? strtolower(substr(strrchr(basename($file), '.'), 1)) : '';
                $dir [$i] ['isDir'] = is_dir($file);
                $dir [$i] ['isFile'] = is_file($file);
                $dir [$i] ['isLink'] = is_link($file);
                $dir [$i] ['isReadable'] = is_readable($file);
                $dir [$i] ['isWritable'] = is_writable($file);
                $i++;
            }
        }
    }
    $cmp_func = create_function('$a,$b', '
		if( ($a["isDir"] && $b["isDir"]) || (!$a["isDir"] && !$b["isDir"]) ){
			return  $a["filename"]>$b["filename"]?1:-1;
		}else{
			if($a["isDir"]){
				return -1;
			}else if($b["isDir"]){
				return 1;
			}
			if($a["filename"]  ==  $b["filename"])  return  0;
			return  $a["filename"]>$b["filename"]?-1:1;
		}
		');
    usort($dir, $cmp_func);
    return $dir;
}

/**
 * 删除文件夹
 * @author rainfer <81818832@qq.com>
 * @param string
 * @param int
 */
function remove_dir($dir, $time_thres = -1)
{
    foreach (list_file($dir) as $f) {
        if ($f ['isDir']) {
            remove_dir($f ['pathname'] . '/');
        } else if ($f ['isFile'] && $f ['filename']) {
            if ($time_thres == -1 || $f ['mtime'] < $time_thres) {
                @unlink($f ['pathname']);
            }
        }
    }
}

/**
 * 格式化字节大小
 * @param  number $size      字节数
 * @param  string $delimiter 数字和单位分隔符
 * @return string            格式化后的带单位的大小
 * @author rainfer <81818832@qq.com>
 */
function format_bytes($size, $delimiter = '') {
    $units = array(' B', ' KB', ' MB', ' GB', ' TB', ' PB');
    for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 返回带协议的域名
 * @author rainfer <81818832@qq.com>
 */
function get_host(){
    $host=$_SERVER["HTTP_HOST"];
    $protocol=Request()->isSsl()?"https://":"http://";
    return $protocol.$host;
}

/**
 * 生成ajax翻页
 * @param $data
 */
function get_ajax_page($data){
    return preg_replace("(<a[^>]*page[=|/](\d+).+?>(.+?)<\/a>)","<a href='javascript:ajax_page($1);'>$2</a>",$data);
}

/**
 * 是否存在方法
 * @param string $module 模块
 * @param string $controller 待判定控制器名
 * @param string $action 待判定控制器名
 * @return number 方法结果，0不存在控制器 1存在控制器但是不存在方法 2存在控制和方法
 */
function has_action($module,$controller,$action){
    $arr=cache('controllers'.'_'.$module);
    if(empty($arr)){
        $arr=\utils\ReadClass::readDir(APP_PATH. $module. DS .'controller');
        cache('controllers'.'_'.$module,$arr);
    }
    if((!empty($arr[$controller])) && $arr[$controller]['class_name']==$controller ){
        $method_name=array_map('array_shift',$arr[$controller]['method']);
        if(in_array($action, $method_name)){
            return 2;
        }else{
            return 1;
        }
    }else{
        return 0;
    }
}

/**
 * 获取客户端浏览器信息 添加win10 edge浏览器判断
 * @author  Jea杨
 * @return string
 */
function getBroswer()
{
    $sys = $_SERVER['HTTP_USER_AGENT'];  //获取用户代理字符串
    if (stripos($sys, "Firefox/") > 0) {
        preg_match("/Firefox\/([^;)]+)+/i", $sys, $b);
        $exp[0] = "Firefox";
        $exp[1] = $b[1];  //获取火狐浏览器的版本号
    } elseif (stripos($sys, "Maxthon") > 0) {
        preg_match("/Maxthon\/([\d\.]+)/", $sys, $aoyou);
        $exp[0] = "傲游";
        $exp[1] = $aoyou[1];
    } elseif (stripos($sys, "MSIE") > 0) {
        preg_match("/MSIE\s+([^;)]+)+/i", $sys, $ie);
        $exp[0] = "IE";
        $exp[1] = $ie[1];  //获取IE的版本号
    } elseif (stripos($sys, "OPR") > 0) {
        preg_match("/OPR\/([\d\.]+)/", $sys, $opera);
        $exp[0] = "Opera";
        $exp[1] = $opera[1];
    } elseif (stripos($sys, "Edge") > 0) {
        //win10 Edge浏览器 添加了chrome内核标记 在判断Chrome之前匹配
        preg_match("/Edge\/([\d\.]+)/", $sys, $Edge);
        $exp[0] = "Edge";
        $exp[1] = $Edge[1];
    } elseif (stripos($sys, "Chrome") > 0) {
        preg_match("/Chrome\/([\d\.]+)/", $sys, $google);
        $exp[0] = "Chrome";
        $exp[1] = $google[1];  //获取google chrome的版本号
    } elseif (stripos($sys, 'rv:') > 0 && stripos($sys, 'Gecko') > 0) {
        preg_match("/rv:([\d\.]+)/", $sys, $IE);
        $exp[0] = "IE";
        $exp[1] = $IE[1];
    } elseif (stripos($sys, 'Safari') > 0) {
        preg_match("/safari\/([^\s]+)/i", $sys, $safari);
        $exp[0] = "Safari";
        $exp[1] = $safari[1];
    } else {
        $exp[0] = "未知浏览器";
        $exp[1] = "";
    }
    return $exp[0] . '(' . $exp[1] . ')';
}

/**
 * 获取客户端操作系统信息包括win10
 * @author  Jea杨
 * @return string
 */
function getOs()
{
    $agent = $_SERVER['HTTP_USER_AGENT'];

    if (preg_match('/win/i', $agent) && strpos($agent, '95')) {
        $os = 'Windows 95';
    } else if (preg_match('/win 9x/i', $agent) && strpos($agent, '4.90')) {
        $os = 'Windows ME';
    } else if (preg_match('/win/i', $agent) && preg_match('/98/i', $agent)) {
        $os = 'Windows 98';
    } else if (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent)) {
        $os = 'Windows Vista';
    } else if (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent)) {
        $os = 'Windows 7';
    } else if (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent)) {
        $os = 'Windows 8';
    } else if (preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent)) {
        $os = 'Windows 10';#添加win10判断
    } else if (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent)) {
        $os = 'Windows XP';
    } else if (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent)) {
        $os = 'Windows 2000';
    } else if (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent)) {
        $os = 'Windows NT';
    } else if (preg_match('/win/i', $agent) && preg_match('/32/i', $agent)) {
        $os = 'Windows 32';
    } else if (preg_match('/linux/i', $agent)) {
        $os = 'Linux';
    } else if (preg_match('/unix/i', $agent)) {
        $os = 'Unix';
    } else if (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent)) {
        $os = 'SunOS';
    } else if (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent)) {
        $os = 'IBM OS/2';
    } else if (preg_match('/Mac/i', $agent)) {
        $os = 'Mac';
    } else if (preg_match('/PowerPC/i', $agent)) {
        $os = 'PowerPC';
    } else if (preg_match('/AIX/i', $agent)) {
        $os = 'AIX';
    } else if (preg_match('/HPUX/i', $agent)) {
        $os = 'HPUX';
    } else if (preg_match('/NetBSD/i', $agent)) {
        $os = 'NetBSD';
    } else if (preg_match('/BSD/i', $agent)) {
        $os = 'BSD';
    } else if (preg_match('/OSF1/i', $agent)) {
        $os = 'OSF1';
    } else if (preg_match('/IRIX/i', $agent)) {
        $os = 'IRIX';
    } else if (preg_match('/FreeBSD/i', $agent)) {
        $os = 'FreeBSD';
    } else if (preg_match('/teleport/i', $agent)) {
        $os = 'teleport';
    } else if (preg_match('/flashget/i', $agent)) {
        $os = 'flashget';
    } else if (preg_match('/webzip/i', $agent)) {
        $os = 'webzip';
    } else if (preg_match('/offline/i', $agent)) {
        $os = 'offline';
    } elseif (preg_match('/ucweb|MQQBrowser|J2ME|IUC|3GW100|LG-MMS|i60|Motorola|MAUI|m9|ME860|maui|C8500|gt|k-touch|X8|htc|GT-S5660|UNTRUSTED|SCH|tianyu|lenovo|SAMSUNG/i', $agent)) {
        $os = 'mobile';
    } else {
        $os = '未知操作系统';
    }
    return $os;
}

//获取导出数据
function getExport($list,$fileName='',$type='xlsx'){
    $fileName = $fileName?:'数据表格';
    $fileName.='-'.date('YmdHis');
    //得到表头
    $top = array_intersect_key($list[0]);
    return [
        'fileName'=>$fileName,
        'top'=>$top,
        'data'=>$list,
        'type'=>$type,
    ];
}

//给 json 助手函数用
function getJson($msg='ok',$code=1,$data=[]){
    return [
        'msg'=>$msg,
        'data'=>$data,
        'code'=>$code,
    ];
}
function success($msg,$data=[]){
    error($msg,1,$data);
}
function error($msg,$code=0,$data=[]){
    @header('Content-Type: application/json');
    echo json_encode(['code'=>$code,'msg'=>$msg,'data'=>$data],320);
    exit;
}